import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:amap_location_fluttify/amap_location_fluttify.dart';
import 'package:convert/convert.dart';
import 'package:date_format/date_format.dart';
import 'package:device_manager/device_manager.dart';
import 'package:flutter/material.dart';
import 'package:flutter_broadcasts/flutter_broadcasts.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_usb_event/flutter_usb_event.dart';
import 'package:get/get.dart';
import 'package:palmf_hid/common/apis/api.dart';
import 'package:palmf_hid/common/services/Db.dart';
import 'package:palmf_hid/common/utils/order_util/common_order_util.dart';
import 'package:palmf_hid/common/utils/order_util/order_utils.dart';
import 'package:palmf_hid/common/utils/permission/permission_utils.dart';
import 'package:palmf_hid/common/utils/utils.dart';
import 'package:palmf_hid/common/values/conf.dart';
import 'package:palmf_hid/pages/main/data_feed_back.dart';
import 'package:palmf_hid/pages/main/hid_util.dart';
import 'package:palmf_hid/pages/main/show_history_data/data_back_dialog.dart';
import 'package:palmf_hid/pages/setting/setting_view.dart';
import 'package:quick_usb/quick_usb.dart';

import 'home_state.dart';

class HomeLogic extends GetxController {
  final HomeState state = HomeState();
  PageController pageController = PageController();
  Timer? timer;
  UsbConfiguration? configuration;
  Timer? broadcastReceiverTimeOutTimer;
  bool _openDevice = false;
  num? latitude;
  num? longitude;
  List<int> regentParma = [];

  //当前处理中的批次卡编号
  String cardMark = "";

  //待更新批次参数列表
  Map<String, Map<String, dynamic>> regentCardWaitUpdateMap = {};

//是否有同步数据
  bool isHasSyncData = false;

  //是否删除成功
  bool isDeleteSuccess = false;

//同步数据的数量
  int syncDataCount = 0;

  //监听USB设备插拔
  BroadcastReceiver? receiver;

  @override
  Future<void> onInit() async {
    super.onInit();
    if (GetPlatform.isAndroid) {
      receiver = BroadcastReceiver(
        names: <String>[USB_DEVICE_ATTACHED, USB_DEVICE_DETACHED],
      );
    }
    registerBroadcastReceiver();
  }

  void registerBroadcastReceiver() async {
    if (GetPlatform.isAndroid) {
      receiver?.messages.listen((e) {
        MyLogUtil().i("收到广播消息：${e.name}");
        if (e.name == USB_DEVICE_ATTACHED) {
          MyToastUtil.show("Equipment online".tr);
          broadcastReceiverTimeOutTimer =
              Timer(const Duration(milliseconds: 1000 * 10), () {
            MyLogUtil().i("搜索设备");
            getDeviceList();
          });
        } else if (e.name == USB_DEVICE_DETACHED) {
          MyToastUtil.show("Equipment offline".tr);
          _openDevice = false;
          disposeDevice();
          if (null != broadcastReceiverTimeOutTimer) {
            broadcastReceiverTimeOutTimer?.cancel();
          }
        }
      });
      receiver?.start();
    } else if (GetPlatform.isWindows) {
      DeviceManager().addListener(() {
        MyLogUtil().i("有设备插拔");
      });
      FlutterUsbEvent.startListening(
        onDeviceConnected: (deviceName) {
          MyLogUtil().i("设备已$deviceName");
          if (deviceName.contains(V_I_D) && deviceName.contains(P_I_D)) {
            if (state.status == 0) {
              state.status = 1;
              broadcastReceiverTimeOutTimer =
                  Timer(const Duration(milliseconds: 1000 * 10), () {
                MyLogUtil().i("搜索设备");
                getDeviceList();
              });
            }
          }
        },
        onDeviceDisconnected: (deviceName) {
          MyLogUtil().i("设备已断开$deviceName");
          state.status = 0;
        },
      );
    }
  }

  @override
  void dispose() {
    FlutterUsbEvent
        .stopListening(); // Arrêter l'écoute lors de la destruction du widget
    super.dispose();
  }

  location() async {
    //获取当前的权限
    var status = await PermissionUtils.checkLocationPermission();
    MyLogUtil().i(status);
    if (status) {
      final location = await AmapLocation.instance.fetchLocation();
      latitude = location.latLng?.latitude ?? 0;
      longitude = location.latLng?.longitude ?? 0;
      MyLogUtil().i('$latitude,$longitude');
    }
  }

  @override
  void onReady() {
    super.onReady();
    getDeviceList();
  }

  @override
  void onClose() {
    super.onClose();
    if (GetPlatform.isAndroid) {
      receiver?.stop();
    } else if (GetPlatform.isWindows) {
      DeviceManager().dispose();
    }
    disposeDevice();
  }

  Future<void> disposeDevice() async {
    MyLogUtil().i("释放设备");
    state.status = 0;
    state.deviceNum = "";
    regentCardWaitUpdateMap.clear();
    if (null != timer) {
      timer?.cancel();
    }
    if (null != broadcastReceiverTimeOutTimer) {
      broadcastReceiverTimeOutTimer?.cancel();
    }
    if (_openDevice) {
      await QuickUsb.closeDevice();
    }

    if (state.isInit) {
      await QuickUsb.exit();
    }
  }

  getDeviceList({isShowToast = false}) async {
    await disposeDevice();
    if (Platform.isWindows) {
      QuickUsbWindows.registerWith();
    }
    state.isInit = await QuickUsb.init();
    //获取设备列表
    MyLogUtil().i("没有设备列表");
    List<UsbDevice> deviceList = await QuickUsb.getDeviceList();
    if (deviceList.isEmpty) {
      MyLogUtil().i("没有设备列表");
      if (isShowToast) {
        MyToastUtil.show('检测设备连接');
      }
      return;
    }
    var usbDeviceList = deviceList.where((e) {
      return e.vendorId == VENDER_ID && e.productId == PRODUCT_ID;
    }).toList();

    if (usbDeviceList.isEmpty) {
      MyLogUtil().i("没有指定设备");
      MyToastUtil.show("检测设备连接");
      return;
    }

    // 获取设备描述并获取权限
    var descriptions = await QuickUsb.getDeviceDescription(usbDeviceList.first);
    MyLogUtil().i(descriptions);
    // 获取权限
    var hasPermission = await QuickUsb.hasPermission(descriptions.device);
    if (!hasPermission) {
      await QuickUsb.requestPermission(descriptions.device);
    }
    // 打开设备
    _openDevice = await QuickUsb.openDevice(descriptions.device);
    if (_openDevice) {
      configuration = await QuickUsb.getConfiguration(0);
      state.status = 1;
      await QuickUsb.claimInterface(configuration!.interfaces[0]);
      var endpoint = configuration!.interfaces[0].endpoints
          .firstWhere((e) => e.direction == UsbEndpoint.DIRECTION_IN);
      if (null != timer) {
        timer?.cancel();
      }

      timer = Timer.periodic(const Duration(milliseconds: 40), (b) async {
        QuickUsb.bulkTransferIn(endpoint, 64, timeout: 40).then(
            (bulkTransferIn) {
          handleHidBackData(bulkTransferIn);
        }, onError: (e) {}).catchError((e) {});
      });
      sendHeadOrder();
    }
  }

  //发送数据
  void sendData(List<int> data) async {
    if (configuration == null) {
      MyLogUtil().i('设备未连接');
      return;
    }
    var endpoint = configuration!.interfaces[0].endpoints
        .firstWhere((e) => e.direction == UsbEndpoint.DIRECTION_OUT);
    Timer(const Duration(milliseconds: 50), () async {
      try {
        await QuickUsb.bulkTransferOut(endpoint, Uint8List.fromList(data),
            timeout: 1000);
      } catch (e) {
        MyLogUtil().i(e);
      }
    });
  }

  //发送握手指令
  void sendHeadOrder() {
    var data = generateOrderHex(ORDER_HEAD_HANDLE, "");
    sendData(data);
  }

  //发送获取仪器编号指令
  void sendGetDeviceNoOrder() {
    var data = generateOrderHex(ORDER_HEAD_GET_DEVICE_NO, "");
    sendData(data);
  }

  //获取未同步结果总条数
  void sendGetUnSyncDataNumOrder() {
    var data = generateOrderHex(ORDER_HEAD_UNLOAD_SYNC_DATA_NUM, "");
    sendData(data);
  }

  //发送删除指令
  void sendDeleteAllTestDataOrder() {
    showDialog(
        context: Get.context!,
        builder: (ctx) {
          return buildDataBackDialog(
              str: "删除设备全部检测记录",
              onPress: () {
                MyLoadingUtil.showLoading(msg: "删除...");
                isDeleteSuccess = false;
                Timer(const Duration(seconds: 5), () {
                  if (!isDeleteSuccess) {
                    MyLoadingUtil.hideLoading();
                    MyToastUtil.show("fail".tr);
                  }
                });
                var data = generateOrderHex(ORDER_HEAD_DELETE_RESULT, "");
                sendData(data);
              });
        });
  }

  //收到测试完成后回复
  void sendReceiveResultOrder() {
    var data = generateOrderHex(ORDER_HEAD_CHECK_OVER_SEND, '');
    sendData(data);
  }

  //根据用户输入的数量同步
  void sendSyncDataOrderByUserNum(int num) {
    String numStr = intToHex(num);
    for (int i = 0; i < 4 - numStr.length; i++) {
      numStr = "0" + numStr;
    }
    var data = generateOrderHex(ORDER_HEAD_GET_TEST_BY_USER, numStr);
    sendData(data);
  }

  //发送同步全部检测数据
  void sendSyncAllDataOrder() {
    var data = generateOrderHex(ORDER_HEAD_SYNC_DATA_SEND, "");
    sendData(data);
  }

  //获取时间
  void sendGetDeviceTimeOrder() {
    var data = generateOrderHex(ORDER_HEAD_GET_DEVICE_TIME, "");
    sendData(data);
  }

  //发送清除二维码
  void sendClearQrCodeOrder() {
    var data = generateOrderHex(ORDER_HEAD_CLEAR_QR_CODE, "");
    sendData(data);
  }

  //发送设置时间指令
  void sendSetTimeOrder() {
    DateTime dateTime = DateTime.now();
    List<int> timeArr = [
      int.parse(dateTime.year.toString().substring(2)),
      dateTime.month,
      dateTime.day,
      dateTime.hour,
      dateTime.minute,
      dateTime.second
    ];
    var data =
        generateOrderHex(ORDER_HEAD_SET_DEVICE_TIME, intArrToHex(timeArr));
    sendData(data);
  }

  //下发参数
  void sendParamOrder(
      String project,
      int r1,
      int r2,
      int r3,
      int r4,
      int r5,
      int r6,
      int show1,
      int show2,
      int show3,
      int show4,
      int show5,
      int show6) {
    String projectHex = asciiToHex(project);
    num len = (20 - projectHex.length) / 2;
    for (int i = 0; i < len.toInt(); i++) {
      projectHex = projectHex + "20";
    }
    String r1Hex = reverseHex(doubleToHex(r1.toDouble()));
    String r2Hex = reverseHex(doubleToHex(r2.toDouble()));
    String r3Hex = reverseHex(doubleToHex(r3.toDouble()));
    String r4Hex = reverseHex(doubleToHex(r4.toDouble()));
    String r5Hex = reverseHex(doubleToHex(r5.toDouble()));
    String r6Hex = reverseHex(doubleToHex(r6.toDouble()));
    String show1Hex = intToHex(show1);
    String show2Hex = intToHex(show2);
    String show3Hex = intToHex(show3);
    String show4Hex = intToHex(show4);
    String show5Hex = intToHex(show5);
    String show6Hex = intToHex(show6);
    String dataHex =
        "$projectHex$r1Hex$r2Hex$r3Hex$r4Hex$r5Hex$r6Hex$show1Hex$show2Hex$show3Hex$show4Hex$show5Hex$show6Hex";
    MyLogUtil().i("下发参数：$dataHex");
    var data = generateOrderHex(ORDER_HEAD_SET_PARAM, dataHex);
    sendData(data);
  }

  handlerSetting() {
    showModalBottomSheet(
        backgroundColor: Colors.white,
        isScrollControlled: true,
        constraints: BoxConstraints(maxHeight: 0.7.sh, minHeight: 0.5.sh),
        shape: const RoundedRectangleBorder(
            borderRadius: BorderRadius.only(
                topLeft: Radius.circular(20), topRight: Radius.circular(20))),
        context: Get.context!,
        builder: (ctx) {
          return SettingComponent();
        });
  }

  List<int> syncByNumResultArray = [];
  List<int> syncAllArray = [];

  List<int> realTimeCheckResultArray = [];

  void handleHidBackData(Uint8List bulkTransferIn) {
    MyLogUtil().i("收到数据：${hex.encode(bulkTransferIn)}");
    List<int> data = bulkTransferIn.toList().sublist(3);
    String header = hex.encode(bulkTransferIn.sublist(0, 3)).toUpperCase();
    switch (header) {
      //握手指令
      case ORDER_HEAD_HANDLE:
        MyLogUtil().i("握手指令返回");
        state.status = 1;
        sendGetDeviceNoOrder();
        break;

      //返回测试结果
      case ORDER_HEAD_REUSLT_BACK:
        MyLogUtil().i("返回测试结果");
        if (bulkTransferIn[62] == 2 && bulkTransferIn[61] == 1) {
          syncAllArray.clear();
          syncAllArray
              .addAll(bulkTransferIn.sublist(3, bulkTransferIn.length - 3));
          MyLogUtil().i("返回测试结果${syncAllArray.length}");
        } else if (bulkTransferIn[62] == bulkTransferIn[61] &&
            bulkTransferIn[62] == 2) {
          MyLogUtil().i("返回测试结果${syncAllArray.length}");
          if (syncAllArray.length != 58) {
            return;
          }
          syncAllArray.addAll(bulkTransferIn.sublist(3, 11));
          Map<String, dynamic> testResult = readResultBack(syncAllArray);
          state.syncNum = testResult["patientId"].toString() +
              testResult['project'].toString();
          feedBackData(testResult);
          syncAllArray.clear();
        } else {
          realTimeCheckResultArray
              .addAll(bulkTransferIn.sublist(3, bulkTransferIn.length - 3));
        }
        break;
      //用户输入数量同步返回
      case ORDER_HEAD_GET_TEST_BY_USER:
        MyLogUtil().i("[str]");
        if (bulkTransferIn[62] == 2 && bulkTransferIn[61] == 1) {
          syncByNumResultArray.clear();
          syncByNumResultArray
              .addAll(bulkTransferIn.sublist(3, bulkTransferIn.length - 3));
          MyLogUtil().i("返回测试结果${syncByNumResultArray.length}");
        } else if (bulkTransferIn[62] == bulkTransferIn[61]) {
          if (syncByNumResultArray.length != 58) {
            return;
          }
          syncByNumResultArray.addAll(bulkTransferIn.sublist(3, 11));

          Map<String, dynamic> testResult =
              readResultBack(syncByNumResultArray);
          syncByNumResultArray.clear();

          state.syncNum = testResult["patientId"].toString() +
              testResult['project'].toString();

          feedBackData(testResult);
        }

        break;
      // 删除数据指令
      case ORDER_HEAD_DELETE_RESULT:
        MyLogUtil().i("删除测试结果");
        isDeleteSuccess = true;
        MyLoadingUtil.hideLoading();
        MyToastUtil.show("成功");
        break;
      //获取仪器编号
      case ORDER_HEAD_GET_DEVICE_NO:
        state.deviceNum = readDeviceNo(bulkTransferIn);
        MyLogUtil().i("获取仪器编号${state.deviceNum} ");
        sendGetUnSyncDataNumOrder();
        break;
      //获取时间返回
      case ORDER_HEAD_GET_DEVICE_TIME:
        int year = DateTime.now().year;
        MyToastUtil.show(
            '${year.toString().substring(0, 2)}${bulkTransferIn[3].toString()}年${bulkTransferIn[4].toString()}月${bulkTransferIn[5].toString()}日${bulkTransferIn[6].toString()}时${bulkTransferIn[7].toString()}分${bulkTransferIn[8].toString()}秒',
            duration: Duration(seconds: 3));
        break;
      //清除二维码
      case ORDER_HEAD_CLEAR_QR_CODE:
        MyToastUtil.show("成功");
        break;
      //设置时间
      case ORDER_HEAD_SET_DEVICE_TIME:
        MyToastUtil.show("成功");
        break;
      //插入卡
      case ORDER_HEAD_CARD_IN:
        MyLogUtil().i("插入卡");
        break;
      //播出卡
      case ORDER_HEAD_CARD_OUT:
        MyLogUtil().i("播出卡");
        break;
      //测试完成
      case ORDER_HEAD_TEST_OVER:
        MyLogUtil().i("测试完成");
        sendReceiveResultOrder();
        MyLogUtil().i("返回测试结果${realTimeCheckResultArray.length}");

        if (realTimeCheckResultArray.length == 58) {
          realTimeCheckResultArray.addAll(bulkTransferIn.sublist(3, 11));
          Map<String, dynamic> testResult =
              readResultBack(realTimeCheckResultArray);
          state.syncNum = testResult["patientId"].toString() +
              testResult['project'].toString();
          feedBackData(testResult);
        } else if (realTimeCheckResultArray.length == 58 * 2) {
          List<int> tempArr = [];
          tempArr.addAll(realTimeCheckResultArray.sublist(0, 58));
          tempArr.addAll(bulkTransferIn.sublist(3, 11));
          MyLogUtil().i("返回测试结果${tempArr.length}");
          Map<String, dynamic> testResult;
          testResult = readResultBack(tempArr);
          state.syncNum = testResult["patientId"].toString() +
              testResult['project'].toString();
          feedBackData(testResult);

          List<int> tempArrTwo = [];
          tempArrTwo.addAll(realTimeCheckResultArray.sublist(58));
          tempArrTwo.addAll(bulkTransferIn.sublist(3, 11));
          MyLogUtil().i("返回测试结果${tempArrTwo.length}");
          testResult = readResultBack(tempArrTwo);
          state.syncNum = testResult["patientId"].toString() +
              testResult['project'].toString();
          feedBackData(testResult);
        } else if (realTimeCheckResultArray.length == 58 * 3) {
          List<int> tempArr = [];
          tempArr.addAll(realTimeCheckResultArray.sublist(0, 58));
          tempArr.addAll(bulkTransferIn.sublist(3, 11));
          MyLogUtil().i("返回测试结果1${tempArr.length}");
          Map<String, dynamic> testResult;
          testResult = readResultBack(tempArr);
          state.syncNum = testResult["patientId"].toString() +
              testResult['project'].toString();
          feedBackData(testResult);

          List<int> tempArrTwo = [];
          tempArrTwo.addAll(realTimeCheckResultArray.sublist(58));
          tempArrTwo.addAll(bulkTransferIn.sublist(3, 11));
          MyLogUtil().i("返回测试结果2${tempArrTwo.length}");
          testResult = readResultBack(tempArrTwo);
          state.syncNum = testResult["patientId"].toString() +
              testResult['project'].toString();
          feedBackData(testResult);

          List<int> tempArrThree = [];
          tempArrThree.addAll(realTimeCheckResultArray.sublist(58 * 2));
          tempArrThree.addAll(bulkTransferIn.sublist(3, 11));
          MyLogUtil().i("返回测试结果3${tempArrThree.length}");
          testResult = readResultBack(tempArrThree);
          state.syncNum = testResult["patientId"].toString() +
              testResult['project'].toString();
          feedBackData(testResult);
        }
        realTimeCheckResultArray.clear();
        break;
      //未同步检测结果的总条数
      case ORDER_HEAD_UNLOAD_SYNC_DATA_NUM:
        int syncDataNum = int.parse(intArrToHex(data.sublist(0, 2)), radix: 16);
        MyLogUtil().i("未同步检测结果的总条数$syncDataNum");
        break;
      //未同步检测结果的数量时，返回没有
      case ORDER_HEAD_SYNC_DATA_NUM_NO_DATA:
        MyLogUtil().i("未同步检测结果的数量时，返回没有");
        break;
    }
  }

  void feedBackData(testResult) {
    DateTime? palmfTime = null;
    if (testResult.containsKey('deviceTime')) {
      var palmfTimeArr = testResult['deviceTime'];
      //返回的日期格式为 【24,10,31,14,31,5】转化为时间字符串格式
      palmfTime = DateTime(DateTime.now().year, palmfTimeArr[1],
          palmfTimeArr[2], palmfTimeArr[3], palmfTimeArr[4], palmfTimeArr[5]);
    }
    MyLogUtil().i(testResult["jointInspectionNo"]);
    dataFeedback(
      palmfTime: palmfTime,
      jointInspectionNo: testResult.containsKey('jointInspectionNo')
          ? testResult["jointInspectionNo"]
          : null,
      jointInspectionNum: testResult.containsKey('jointInspectionNum')
          ? testResult["jointInspectionNum"]
          : null,
      "HID",
      testResult["project"],
      testResult["resultUnit"],
      testResult["result"],
      testResult["curveBatchNoFromPalmf"],
      testResult["sample"],
      testResult["resultDisplay"],
      state.deviceNum,
      testResult["saveNum"],
      testResult["patientId"],
      "",
      "",
      "",
      "",
      testResult["referLower"],
      testResult["referUpper"],
      testResult["curveVersion"],
    );
  }

  // 最近三条记录
  Future<void> getHistoryList() async {
    var value = await DbService.to.allResultDataByPage(5, 0, "", "", "");
    state.historyResultList(value);
    state.historyResultList.refresh();
  }

  queryResultUnUpload() {
    DbService.to.queryResultUnUpload().then((value) {
      if (value.isNotEmpty) {
        value.forEach((element) {
          MyLogUtil().i(element.toJson());
          Map<String, dynamic> params = {};
          params["projectName"] =
              element.projectName.replaceAll('\u0000', "").replaceAll(" ", "");
          params["sample"] = element.sample == -1 ? "" : element.sample;
          params["resultUnit"] =
              element.resultUnit.replaceAll('\u0000', "").replaceAll(" ", "");
          params["resultDisplay"] = element.resultDisplay;
          params["result"] = element.result
              .toString()
              .replaceAll('\u0000', "")
              .replaceAll(" ", "");
          params["deviceNo"] = element.deviceNo;
          params["time"] = formatDate(element.time,
              [yyyy, '-', mm, '-', dd, " ", HH, ':', nn, ':', ss]);

          params["patientId"] = element.patientId;
          params["position"] = element.position;
          params["scale"] = element.saveNum;
          params["mac"] = element.mac;
          params["curveBatchNo"] = element.curveBatchNo;
          params["curveVersion"] = element.identityCode;
          MyLogUtil().i('上传服务器参数(上次没有成功的)：$params');
          ApiRepository.dataBackup(params).then((value) {
            if (value.code == 0) {
              DbService.to.updateResultUpload(element.id);
            }
          });
        });
      }
    });
  }
}
